from typing import List

from llvmlite import ir
from .base import PMBuiltinFunction, get_function_cls


class PMSqrt(PMBuiltinFunction):

    def __init__(self):
        super().__init__('sqrt')

    def __call__(self, builder: ir.IRBuilder, args: List = None, arg_types: List = None, name=''):
        from ..builtin_func_types import builtins
        from ...types import PMBasicType, double
        assert len(args) == len(arg_types) == 1
        assert args[0].type == double
        return builtins.sqrt(builder, args, name), PMBasicType(double)


class PMLogFunc(PMBuiltinFunction):

    def __init__(self):
        super().__init__('log')

    def __call__(self, builder: ir.IRBuilder, args: List = None, arg_types: List = None, name=''):
        from ..builtin_func_types import builtins
        from ...types import PMBasicType, double
        assert len(args) == len(arg_types) == 1
        assert args[0].type == double
        return builtins.log(builder, args, name), PMBasicType(double)


class PMCosine(PMBuiltinFunction):

    def __init__(self):
        super().__init__('cos')

    def __call__(self, builder: ir.IRBuilder, args: List = None, arg_types: List = None, name=''):
        from ..builtin_func_types import builtins
        from ...types import PMBasicType, double
        assert len(args) == len(arg_types) == 1
        assert args[0].type == double
        return builtins.cosine(builder, args, name), PMBasicType(double)


class PMSine(PMBuiltinFunction):

    def __init__(self):
        super().__init__('sin')

    def __call__(self, builder: ir.IRBuilder, args: List = None, arg_types: List = None, name=''):
        from ..builtin_func_types import builtins
        from ...types import PMBasicType, double
        assert len(args) == len(arg_types) == 1
        assert args[0].type == double
        return builtins.sine(builder, args, name), PMBasicType(double)


math_function_interfaces = get_function_cls(globals())
